#pragma once

#include <AEEStdErr.h>
#include "fastcv/fastcv.h"
#include "fastcv/fastcvExt.h"

#include <assert.h>
#include <type_traits>

#define DECLARE_FUNC(name) std::decay_t<decltype(name)> dl_##name = NULL;


#define LOAD_FUNC(name) do{ \
    dl_##name = (std::decay_t<decltype(name)>)FcvContext::loadFunc(#name); \
    if(dl_##name == NULL) { \
        FARF(ERROR,"Failed to load the symbol: "#name" from libfastcvadsp.so"); \
        return AEE_EUNABLETOLOAD; \
    } \
} while (0)

#define CALL_FCV_FUNC(name, ...)  dl_##name(__VA_ARGS__)


class FcvContext
{
public:
    static FcvContext *getContext();

    static void * loadFunc(const char *name);

    DECLARE_FUNC(fcvGetVersion);
    DECLARE_FUNC(fcvMemAlloc);
    DECLARE_FUNC(fcvMemFree);
    DECLARE_FUNC(fcvSetOperationMode);
    DECLARE_FUNC(fcvCleanUp);

    DECLARE_FUNC(fcvScaleu8);
    DECLARE_FUNC(fcvScaleDownBLu8);
    DECLARE_FUNC(fcvAddScalarf32);
    DECLARE_FUNC(fcvMultiplyScalarf32);
    DECLARE_FUNC(fcvElementMultiplyf32);
    DECLARE_FUNC(fcvMatrixMultiplyf32);
    DECLARE_FUNC(fcvMatrixMultiplys8s32);

    DECLARE_FUNC(fcvMinMaxLocf32);
    DECLARE_FUNC(fcvMinMaxLocu8);
    DECLARE_FUNC(fcvMinMaxLocs16);

    DECLARE_FUNC(fcvTransposeu16);

    DECLARE_FUNC(fcvFFTu8)
    DECLARE_FUNC(fcvIFFTf32);
    DECLARE_FUNC(fcvDCTu8);
    DECLARE_FUNC(fcvIDCTs16);

    FcvContext();
    ~FcvContext();

    int init();
    void deinit();

private:
    int ref_cnt;
};
